package com.huidu.bitrade.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.huidu.bitrade.constant.TransactionType;
import com.huidu.bitrade.dto.MemberParentDTO;
import com.huidu.bitrade.dto.MemberParentUserDTO;
import com.huidu.bitrade.entity.*;
import com.huidu.bitrade.entity.transform.AuthMember;
import com.huidu.bitrade.enums.MemberStarEnum;
import com.huidu.bitrade.exception.ServiceException;
import com.huidu.bitrade.service.*;
import com.google.common.collect.Lists;
import com.huidu.bitrade.entity.AcReferrerRewards;
import com.huidu.bitrade.entity.Member;
import com.huidu.bitrade.entity.MemberWallet;
import com.huidu.bitrade.entity.OtcCoin;
import com.huidu.bitrade.service.*;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;

@Service("DefaultPurchaseService")
@Slf4j
public class DefaultPurchaseService implements PurchaseService {

    @Autowired
    @Qualifier("CnhdPurchaseService")
    private PurchasePayService cnhdPurchasePayService;
    @Autowired
    @Qualifier("HdzPurchaseService")
    private PurchasePayService hdzPurchasePayService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private NewMemberService newMemberService;
    @Autowired
    private AcReferrerRewardsServiceImpl referrerRewardsService;
    @Autowired
    private MemberWalletService memberWalletService;
    @Autowired
    private LocaleMessageSourceService msService;

    @Override
    public boolean purchaseHandle(AuthMember authMember, MemberStarEnum starEnum, Integer purchaseCount, Integer payType, BigDecimal currentHdz) {
        String batchCode = UUID.randomUUID().toString();
        if(payType == 1){
            //币本位+金本位购买
            hdzPurchasePayService.purchase(payType,authMember, starEnum,purchaseCount,batchCode,currentHdz);
            cnhdPurchasePayService.purchase(payType,authMember, starEnum,purchaseCount,batchCode,currentHdz);
        }else if(payType == 2){
            //金本位购买
            cnhdPurchasePayService.purchase(payType,authMember,starEnum,purchaseCount,batchCode,currentHdz);
        }
        return true;
    }

    @Override
    public boolean purchaseHandleImport(AuthMember authMember, MemberStarEnum starEnum, Integer purchaseCount, Integer payType, BigDecimal currentHdz) {
        String batchCode = UUID.randomUUID().toString();
        hdzPurchasePayService.purchaseImport(payType,authMember, starEnum,purchaseCount,batchCode,currentHdz);
        cnhdPurchasePayService.purchaseImport(payType,authMember, starEnum,purchaseCount,batchCode,currentHdz);
        return true;
    }

    @Override
    public Member getMember(Long id){
        return memberService.findOne(id);
    }

    @Override
    public void updateMember(Member member, MemberStarEnum starEnum) throws ServiceException {
        int row = newMemberService.updateMemberStar(member.getId(),starEnum.getLevel(),starEnum.getCount());
        if(row!=1){
            throw new ServiceException("当前节点信息有误，请刷新后重试");
        }
    }

//    @Override
//    public void distribute(){
//        DefaultPurchaseService defaultPurchaseService = SpringContextUtils.getApplicationContext().getBean(DefaultPurchaseService.class);
//        List<MemberParentUserDTO> userParentList = newMemberService.findUserAndParent();
//        Assert.isTrue(CollectionUtils.isNotEmpty(userParentList),msService.getMessage("NO_USERS_WITH_STAR_RATINGS_WERE_FOUND"));
//        for (MemberParentUserDTO member : userParentList) {
//            List<MemberParentDTO> parentList = member.getParentId();
//            if(CollectionUtils.isEmpty(parentList)){
//                continue;
//            }
//            //创建事务发放
//            transactionTemplate.execute((TransactionCallback) transactionStatus -> {
//                try {
//                    defaultPurchaseService.saveRecord(member, parentList);
//                    return true;
//                } catch (Exception exception) {
//                    log.info("执行事务异常，需要回滚");
//                    transactionStatus.setRollbackOnly();
//                    return false;
//                }
//            });
//        }
//    }

    /**
     * 存储记录表
     */
    public void saveRecord(MemberParentUserDTO member, List<MemberParentDTO> parentList) {
        //如果第一个，也就是直推是7星，直接拿18%
        MemberParentDTO memberParentDTO = parentList.get(0);
        if(Objects.equals(memberParentDTO.getMemberStar(), MemberStarEnum.LEVEL_SEVEN.getLevel())){
            log.info("查询到7星推荐人，当前用户id:{}，7星推荐人id:{}", member.getId(),memberParentDTO.getId());
            AcReferrerRewards award = award(member, memberParentDTO, SUPER_LEVEL);
            increaseBalance(award);
            referrerRewardsService.save(award);
            return;
        }
        List<AcReferrerRewards> referrerRewardList = Lists.newArrayList();
        for (int i = 0; i < parentList.size(); i++) {
            AcReferrerRewards award = award(member, parentList.get(i), AWARD.get(i));
            increaseBalance(award);
            referrerRewardList.add(award);
        }
        if(CollectionUtils.isNotEmpty(referrerRewardList)){
            referrerRewardsService.saveBatch(referrerRewardList);
        }
    }

    /**
     * 修改推荐人重新发奖励使用
     * @param member
     * @param parentList
     */
    public void rollRecord(MemberParentUserDTO member, List<MemberParentDTO> parentList) {
        //如果第一个，也就是直推是7星，直接拿18%
        MemberParentDTO memberParentDTO = parentList.get(0);
        if(Objects.equals(memberParentDTO.getMemberStar(), MemberStarEnum.LEVEL_SEVEN.getLevel())){
            log.info("查询到7星推荐人，当前用户id:{}，7星推荐人id:{}", member.getId(),memberParentDTO.getId());
            AcReferrerRewards award = rollAward(member, memberParentDTO, SUPER_LEVEL);
            increaseBalance(award);
            referrerRewardsService.save(award);
            return;
        }
        List<AcReferrerRewards> referrerRewardList = Lists.newArrayList();
        for (int i = 0; i < parentList.size(); i++) {
            AcReferrerRewards award = rollAward(member, parentList.get(i), AWARD.get(i));
            increaseBalance(award);
            referrerRewardList.add(award);
        }
        if(CollectionUtils.isNotEmpty(referrerRewardList)){
            referrerRewardsService.saveBatch(referrerRewardList);
        }
    }

    private AcReferrerRewards rollAward(MemberParentUserDTO member,MemberParentDTO parent, Data awardData) {
        BigDecimal cnhd = member.getMemberStar().getCnhd();
        return AcReferrerRewards.builder()
                .memberId(member.getId())
                .toMemberId(parent.getId())
                .toMemberStar(parent.getMemberStar())
                .memberStar(member.getMemberStar().getLevel())
                .proportion(awardData.getAward())
                .referrerLevel(awardData.getLevel())
                .money(cnhd)
                .type("CNHD")
                .number(cnhd.multiply(awardData.getAward()))
                .build();
    }

    /**
     * 升星奖励推荐人
     */
    public void upgradeStar(Long uid, Integer oldStar) {
        MemberParentUserDTO memberParentUserDTO = newMemberService.findUserAndParentById(uid);
        if (CollectionUtils.isEmpty(memberParentUserDTO.getParentId())) {
            log.info("未查询到推荐人，memberId:{}", uid);
            return;
        }
        oldStar = null == oldStar ? 0 : oldStar;
        memberParentUserDTO.setOldStar(MemberStarEnum.getByLevel(oldStar));
        saveRecord(memberParentUserDTO,memberParentUserDTO.getParentId());
    }

    /**
     * 修改用户账户余额
     * @param referrerRewards
     */
    private void increaseBalance(AcReferrerRewards referrerRewards) {
        OtcCoin otcCoin = new OtcCoin();
        otcCoin.setUnit(referrerRewards.getType());
        MemberWallet memberWallet = memberWalletService.findByOtcCoinAndMemberId(otcCoin, referrerRewards.getToMemberId());
        if(Objects.isNull(memberWallet)){
            referrerRewards.setFail(msService.getMessage("THE_USER_DOES_NOT_HAVE_THIS_TYPE_OF_WALLET"));
            return;
        }
        memberWalletService.operateIncreaseBalance(memberWallet,referrerRewards.getNumber(), TransactionType.PROMOTION_AWARD);
    }

    /**
     *
     * @param member
     * @param parent
     * @param awardData 奖励比例
     * @return
     */
    private AcReferrerRewards award(MemberParentUserDTO member,MemberParentDTO parent, Data awardData) {
//        BigDecimal cnhd = member.getMemberStar().getCnhd();
        BigDecimal newCnhd = member.getMemberStar().getCnhd();
        BigDecimal oldCnhd = member.getOldStar().getCnhd();
        BigDecimal cnhd = newCnhd.subtract(oldCnhd);
        return AcReferrerRewards.builder()
                .memberId(member.getId())
                .toMemberId(parent.getId())
                .toMemberStar(parent.getMemberStar())
                .memberStar(member.getMemberStar().getLevel())
                .proportion(awardData.getAward())
                .referrerLevel(awardData.getLevel())
                .money(cnhd)
                .type("CNHD")
                .number(cnhd.multiply(awardData.getAward()))
                .build();
    }

    @PostConstruct
    public void init(){
        AWARD = Lists.newArrayList();
        //直推奖励
        AWARD.add(new Data(BigDecimal.valueOf(0.10),1));
        //间接奖励
        AWARD.add(new Data(BigDecimal.valueOf(0.05),2));
        //3代奖励
        AWARD.add(new Data(BigDecimal.valueOf(0.03),3));
    }

    @lombok.Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class Data{
        //奖励
        private BigDecimal award;
        //第几代推荐人
        private Integer level;
    }

    private static List<Data> AWARD = null;
    //7星推荐人
    private final static Data SUPER_LEVEL = new Data(BigDecimal.valueOf(0.18),0);


}
